package com.webchat.chat.core.listener;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.webchat.chat.core.dto.evenMessage.MsgInfo;
import com.webchat.chat.core.enums.MsgType;
import com.webchat.chat.core.enums.SocketRoomStatus;
import com.webchat.chat.core.redis.RedisService;
import com.webchat.chat.core.shiro.ShiroUser;
import com.webchat.chat.core.tools.ChatConstant;
import com.webchat.chat.core.tools.RedisConstant;
import com.webchat.chat.core.tools.SocketConstant;
import com.webchat.chat.core.tools.SpringBeanFactoryUtils;
import com.webchat.chat.model.SocketClient;
import com.webchat.chat.model.SocketRoom;
import com.webchat.chat.service.SocketClientService;
import com.webchat.chat.service.SocketRoomService;
import com.webchat.chat.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by Owner on 2018/6/27.
 */
public class ShiroSessionListener implements SessionListener {

    private static final Logger logger = LoggerFactory.getLogger(ShiroSessionListener.class);

    @Resource
    private SocketRoomService socketRoomService;

    @Resource
    private SocketClientService socketClientService;

    @Resource
    private RedisService redisService;

    @Resource
    private SocketIOServer socketIOServer;

    @Resource
    private UserService userService;

    /**
     * 用于操作缓存的session
     */
    @Resource
    SessionDAO sessionDAO;

    /**
     * 会话创建的时候触发
     *
     * @param session
     */
    @Override
    public void onStart(Session session) {
        long timeout = session.getTimeout();
        Serializable id = session.getId();
        Date startTimestamp = session.getStartTimestamp();
        Date lastAccessTime = session.getLastAccessTime();

        logger.info("\n会话ID[{}]；\n会话超时时长[{}];\n开始访问时间[{}];\n最后访问时间[{}]\n", id, timeout, startTimestamp, lastAccessTime);
//        //登陆成功之后将用户ID保存到session
//        session.setAttribute(OxygenConstant.SHIRO_USER_IN_SESSION, ShiroUtil.getCurShiroUser());
    }

    /**
     * 会话过期时触发
     *
     * @param session
     */
    @Override
    public void onStop(Session session) {
        Serializable id = session.getId();
        ShiroUser shiroUser = (ShiroUser) session.getAttribute(ChatConstant.SHIRO_USER_IN_SESSION);
        session.removeAttribute(ChatConstant.SHIRO_USER_IN_SESSION);
        String userId = shiroUser.getUserId();
        String userName = shiroUser.getUserName();
        logger.info("\n{}\n会话到期1;\n用户名[{}];\n用户ID[{}]", id, userId, userName);
        clearData(shiroUser);
    }

    /**
     * 退出、会话失效时触发
     *
     * @param session
     */
    @Override
    public void onExpiration(Session session) {
        ShiroUser shiroUser = (ShiroUser) session.getAttribute(ChatConstant.SHIRO_USER_IN_SESSION);
        String userId = shiroUser.getUserId();
        String userName = shiroUser.getUserName();
        if (socketClientService == null) {
            socketClientService = SpringBeanFactoryUtils.getBean(SocketClientService.class);
        }
        SocketClient client = socketClientService.findSocketClientByUserId(userId);

        Long mostSignificantBits = client.getMostSignificantBits();
        Long leastSignificantBits = client.getLeastSignificantBits();
        if (mostSignificantBits == null || leastSignificantBits == null) {
            return;
        }
        UUID uuid = new UUID(mostSignificantBits, leastSignificantBits);
        if (socketIOServer == null) {
            socketIOServer = SpringBeanFactoryUtils.getBean(SocketIOServer.class);
        }
        SocketIOClient socketIOClient = socketIOServer.getClient(uuid);
        MsgInfo msgInfo = new MsgInfo();
        msgInfo.setMsgType(MsgType.推送通知);
        msgInfo.setContent("服务超时， 请重新登录！！");
        socketIOClient.sendEvent(SocketConstant.TIME_OUT_EVENT, msgInfo);

        clearData(shiroUser);

    }

    private void clearData(ShiroUser shiroUser) {
        Date now = new Date();
        String userId = shiroUser.getUserId();
        String tenantCode = shiroUser.getTenantCode();
        String clientId;
        //清楚通信密码
        if (userService == null) {
            userService = SpringBeanFactoryUtils.getBean(UserService.class);
        }
        userService.changeStatusOffline(userId);

        if (redisService == null) {
            redisService = SpringBeanFactoryUtils.getBean(RedisService.class);
        }
        redisService.removeMapField(RedisConstant.PWD_CONNECT, userId);
        redisService.removeMapField(RedisConstant.User_Session,userId);
        if (socketClientService == null) {
            socketClientService = SpringBeanFactoryUtils.getBean(SocketClientService.class);
        }
        SocketClient socketClient = socketClientService.findSocketClientByUserId(userId);
        if (socketClient != null) {
            clientId = socketClient.getClientId();
            if (StringUtils.isNotBlank(clientId)) {
                if (socketRoomService == null) {
                    socketRoomService = SpringBeanFactoryUtils.getBean(SocketRoomService.class);
                }
                List<SocketRoom> socketRooms = socketRoomService.findSocketRooms(clientId, tenantCode, SocketRoomStatus.正常);
                if (socketRooms != null && !socketRooms.isEmpty()) {
                    socketRooms.forEach(sr -> {
                        sr.setStatus(SocketRoomStatus.断开);
                        Date time = sr.getJoinTime();
                        if (time != null) {
                            sr.setDuration((now.getTime() - time.getTime()) + "");
                        }
                        socketRoomService.update(sr);
                    });
                }
            }
        }

    }
}
